<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es6 继承自内置类的用法</title>
  <!-- 
  在 JavaScript ES6 中，继承内置类（如  `Array` 、 `Date` 、 `Error`  等）允许我们创建自定义类，这些类可以利用内置类的功能，同时扩展或修改它们的行为。
  1. 基本概念
  - 内置类：JavaScript 提供的一些内置构造函数，例如  `Array` 、 `Date` 、 `Error` 、 `RegExp`  等。
  - 继承：通过  `extends`  关键字，子类可以继承父类的属性和方法。

  2. 继承内置类的基本语法
  使用  `class`  关键字和  `extends`  关键字来创建一个继承自内置类的子类。
  class MyArray extends Array {
      // 添加自定义方法
      getFirst() {
          return this[0];
      }
  }

  const myArray = new MyArray(1, 2, 3, 4);
  console.log(myArray.getFirst()); // 输出: 1
  console.log(myArray.length);      // 输出: 4
  3. 继承内置类的注意事项
  - 构造函数：在子类的构造函数中，必须调用  `super()` ，以确保父类的构造函数被正确调用。
  - 实例化：通过  `new`  关键字创建子类的实例时，可以传入父类的构造函数所需的参数。

  4. 扩展内置类的功能
  通过继承内置类，可以添加自定义的方法和属性，扩展其功能。

   示例代码：
  class MyDate extends Date {
      // 添加自定义方法
      getFormattedDate() {
          return `${this.getFullYear()}-${this.getMonth() + 1}-${this.getDate()}`;
      }
  }

  const myDate = new MyDate();
  console.log(myDate.getFormattedDate()); // 输出: 当前日期，格式为 YYYY-MM-DD
  5. 继承内置类的静态方法
  可以在子类中使用  `super`  调用父类的静态方法。

   示例代码：
  class MyError extends Error {
      constructor(message) {
          super(message); // 调用父类构造函数
          this.name = 'MyError'; // 自定义错误名称
      }

      static logError(error) {
          console.error(`${error.name}: ${error.message}`);
      }
  }

  const myError = new MyError('Something went wrong.');
  MyError.logError(myError); // 输出: MyError: Something went wrong.
  6. 总结
  在 ES6 中，继承内置类提供了一种灵活的方式来扩展和定制 JavaScript 的内置功能。通过使用  `class`  和  `extends`  关键字，开发者可以创建新的类，这些类不仅具有内置类的特性，还可以添加自定义的属性和方法。这种继承机制使得 JavaScript 的面向对象编程更加强大和灵活。理解如何继承内置类对于编写高效、可维护的代码非常重要。
   -->
</head>

<body>

  <script>
    // 继承内置 Array 类
    class MyArray extends Array {
      // 添加自定义方法
      getSum() {
        return this.reduce((sum, value) => sum + value, 0);
      }

      // 添加自定义方法
      getAverage() {
        return this.getSum() / this.length;
      }

      get lastItem() {
        return this[this.length - 1]
      }

      get firstItem() {
        return this[0]
      }
    }

    const myArray = new MyArray(1, 2, 3, 4, 5);
    console.log(myArray.getSum()); // 输出: 15
    console.log(myArray.getAverage()); // 输出: 3
    console.log(myArray.lastItem); // 输出: 5
    console.log(myArray.firstItem); // 输出: 1
    console.log(myArray[0], myArray.length); // 输出: 1

    // 2.直接对Array进行扩展
    Array.prototype.lastItem = function() {
      return this[this.length - 1]
    }

    // 函数apply/call/bind方法 -> Function.prototype
    var arr = new Array(10, 20, 30)
    console.log(arr.__proto__ === Array.prototype)
    console.log(arr.lastItem())
    
    // 继承内置 Date 类
    class MyDate extends Date {
      // 添加自定义方法
      getFormattedDate() {
        return `${this.getFullYear()}-${this.getMonth() + 1}-${this.getDate()}`;
      }
    }

    const myDate = new MyDate();
    console.log(myDate.getFormattedDate()); // 输出: 当前日期，例如: 2022-1-1

  </script>

</body>

</html>